/*
 *  Copyright (C) 2010:
 *                 Buzzanca Marco <marco.bzn@gmail.com>
 *         Monaco Davide Giuseppe <black.ralkass@gmail.com>
 *              Petralia Veronica <veronicapetralia@gmail.com>
 *
 * This file is part of DS2011BMP
 *
 * DS2011BMP is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DS2011BMP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

/**
 * @file workerdiscovery.cpp
 * @author Marco Buzzanca
 *
 * This file contains WorkerDiscovery class implementation.
 */

#include "workerdiscovery.h"

void WorkerDiscovery::serve(UDPServer::Responder responder)
{
    TaskDescriptor td;

    responder >> td;
    responder << getWorker(td);
}

void WorkerDiscovery::run(void)
{
    _server.bind();

    std::cout << "Discovery ready." << std::endl;

    for (;;)
    {
        // Receives response, creates a Responder object.
        boost::thread(&WorkerDiscovery::serve, this, _server.receive());
    }
}

Address WorkerDiscovery::getWorker(const TaskDescriptor& td)
{
    boost::mutex::scoped_lock lock(_mutex);

    std::vector<WorkerDescriptor>::size_type i;

    for (i = 0; i < _workers.size(); i++)
    {
        // No resource is taken into account right now, just worker status.
        if (_workers[i].getStatus() == Free)
            return _workers[i].getAddress();
    }

    // Invalid address, either this or exception handling. Something like
    // NoFreeWorkersException would do. The proxy could notify the manager
    // there are no free workers either way.
    return Address();
}

void WorkerDiscovery::updateWorker(size_t index, const WorkerDescriptor& wd)
{
    boost::mutex::scoped_lock lock(_mutex);
    _workers[index] = wd;
}

void WorkerDiscovery::addWorker(const WorkerDescriptor& wd)
{
    boost::mutex::scoped_lock lock(_mutex);
    _workers.push_back(wd);
}

void WorkerDiscovery::removeWorker(size_t index)
{
    boost::mutex::scoped_lock lock(_mutex);
    _workers.erase(_workers.begin() + index);
}

void WorkerDiscovery::clear(void)
{
    boost::mutex::scoped_lock lock(_mutex);
    _workers.clear();
}

WorkerDiscovery::collection_size_t WorkerDiscovery::size(void)
{
    boost::mutex::scoped_lock lock(_mutex);
    return _workers.size();
}

bool WorkerDiscovery::empty(void)
{
    boost::mutex::scoped_lock lock(_mutex);
    return _workers.empty();
}

boost::uint16_t WorkerDiscovery::getPort(void) const
{ return _server.getPort(); }

void WorkerDiscovery::setPort(boost::uint16_t port)
{ _server.setPort(port); }

void WorkerDiscovery::setPort(const Address& address)
{ _server.setPort(address.getPort()); }

